#ifndef GRAPH_H
#define GRAPH_H

#include <map>
#include <vector>
#include <iostream>

using namespace std;

class Node {
public:
	Node() : id(0), cid(-1), request_bw(0) { }

	Node(int iid): id(iid), cid(-1), request_bw(0) { }

	void setConsume(int icid, int icon) {
		cid = icid;
		request_bw = icon;
	}

public:
	int id;
	int cid; // consumer id
	int request_bw; // -1 for none
};

class Link {
public:
	Link() : id(-1),
		src(-1), dst(-1),
		total_bw(0), remain_bw(0),
		unit_price(0) { }

	Link(int iid, int isrc, int idst, int itotal_bw, int iremain_bw, int iprice) :
		id(iid), src(isrc), dst(idst),
		total_bw(itotal_bw), remain_bw(iremain_bw),
		unit_price(iprice) { }

public:
	int id;
	int src;
	int dst;
	int total_bw;
	int remain_bw;
	int unit_price;
};

class Graph {
public:
	Graph(int ncnt, int lcnt, int ccnt) :
		node_cnt(ncnt), link_cnt(lcnt), cnode_cnt(ccnt) {

		link_matrix.resize(ncnt);
		for (int i = 0; i < ncnt; i++) {
			link_matrix[i].resize(ncnt);
		}
	}

	void addNode(Node node) {
		node_map[node.id] = node;
	}

	void addLink(Link link) {
		link_matrix[link.src][link.dst] = link;
	}

	Node & getNodeById(int id) {
		return node_map[id];
	}

	Link & getLinkById(int src, int dst) {
		return link_matrix[src][dst];
	}

	void printGraph() {
		cout << "node_cnt = " << node_cnt << std::endl;
		cout << "link_cnt = " << link_cnt << std::endl;
		cout << "consume_cnt = " << cnode_cnt << std::endl;

		cout << "Node Information: " << std::endl;
		for (int i = 0; i < node_cnt; i++) {
			cout << node_map[i].id << " " << node_map[i].cid << " " << node_map[i].request_bw << std::endl;
		}

		cout << "Link Information: "  << std::endl;
		for (int i = 0; i < link_matrix.size(); i++) {
			for (int j = 0; j < link_matrix[i].size(); j++) {
				cout << link_matrix[i][j].id << " " << link_matrix[i][j].src << " " << link_matrix[i][j].dst << std::endl;
			}
		}
	}


public:
	int node_cnt;
	int link_cnt;
	int cnode_cnt;

	map<int, Node> node_map;
	vector<vector<Link> > link_matrix;
};

#endif
